#include "StanzaManager.h"
#include <iostream>

namespace tinkle {

StanzaManager::StanzaManager(Socket &sock, XmlParser &parser) :
_cSocket(sock),
_cParser(parser)
{
	//_cSocket.SigWrite.connect(this, &StanzaManager::_SendStanza);
	_cSocket.SigRead.connect(this, &StanzaManager::_recvfromsocket);
	_cParser.RegisterCallbackFunc(&StanzaManager::_XmlNodeCallBack, this);
}

StanzaManager::~StanzaManager(){		
	_cSocket.SigRead.disconnect(this);
	_cParser.UnregisterCallbackFunc();
	_cParser.Refresh();
	Clear();
}


void StanzaManager::Clear() {
	/*
	while (!_qWriteStanzas.empty() && !_qReserve.empty()) {
		_PopWriteQueue();
	}
	while (!_qWriteStanzas.empty()) _qWriteStanzas.pop();
	while (!_qReserve.empty()) _qReserve.empty();
	*/
	while (!_qWriteStanzas.empty()) _PopWriteQueue();
	while (!_qReadStanzas.empty()) {
		delete _qReadStanzas.front();
		_qReadStanzas.pop();
	}
} 

XmlNode* StanzaManager::Read() {
	if (_qReadStanzas.empty()) {
		return NULL;
	}
	XmlNode* ret = _qReadStanzas.front();
	_qReadStanzas.pop();
	return ret;
}

void StanzaManager::Write(XmlNode *stanza)  {
	_qWriteStanzas.push(stanza);
    _SendStanza(_cSocket);
	//_qReserve.push(bReserve);

	//_cSocket.SigWrite(_cSocket);
}


void StanzaManager::_SendStanza(tinkle::Socket &sock) {
	static int offset = 0;
    static std::string s;
    printf ("Sending...\n");
	/*while  (!_qWriteStanzas.empty()) {
		if (0 == offset) s = _qWriteStanzas.front()->Dump();
        std::cout << "send stanza:" << s << std::endl;
		int ret = sock.Write(s.c_str()+offset, s.length()-offset);        
		if (SOCKET_ERROR == ret) return;
		if ((offset += ret) == s.length()) {
			offset = 0;
            printf ("finish\n");
			_PopWriteQueue();
		}
	}*/
    while (!_qWriteStanzas.empty()) {
        std::string s = _qWriteStanzas.front()->Dump();
        int ret = sock.Write(s.c_str(), s.length());
        _PopWriteQueue();
    }
}


void StanzaManager::_PopWriteQueue() {
	//if (!_qReserve.front())
	delete _qWriteStanzas.front();
	_qWriteStanzas.pop();
	//_qReserve.pop();
}

void StanzaManager::_recvfromsocket(tinkle::Socket &sock) {
	int ret = sock.Read(_Buf, BUFFLEN);
    printf ("recv count:%d, error:%d\n", ret, WSAGetLastError());
	if (SOCKET_ERROR == ret) return;
    std::string s(_Buf, ret);
    printf ("socket str: %s\n", s.c_str());
	_cParser.Parse(s);	
}

void StanzaManager::_XmlNodeCallBack(XmlNode *stanza, void * _mgr) {
	StanzaManager* mgr = (StanzaManager*)_mgr;
	mgr->_qReadStanzas.push(stanza);
	mgr->SigRead(mgr);
}

int StanzaManager::EnableTLS() {
	return _cSocket.EnableTLS();
}

int StanzaManager::DisableTLS() {
	return _cSocket.DisableTLS();
}

bool StanzaManager::IsTLSEnabled() {
	return _cSocket.IsTLSEnabled();
}

}